package com.vdong.common.oauth.common.authorize.util;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.vdong.common.oauth.common.authorize.AuthCommon;
import com.vdong.common.oauth.common.authorize.AuthWebAuthenticationDetails;
import com.vdong.kpay.basics.dubbo.pojo.auth.AuthUser;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;

import java.util.LinkedHashMap;


public class SecurityUtil {
    public static final String USER_AUTHENTICATION = "userAuthentication";
    public static final String DETAILS = "details";

    /**
     * 获取登录用户
     */
    public static AuthUser getAuthUser() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Object principal = authentication.getPrincipal();
        if (authentication != null && principal != null) {
            AuthUser authUser = null;
            if (authentication instanceof PreAuthenticatedAuthenticationToken) {
                PreAuthenticatedAuthenticationToken token = (PreAuthenticatedAuthenticationToken) authentication;
                authUser = (AuthUser) token.getPrincipal();
                return authUser;
            }
            if (authentication instanceof OAuth2Authentication) {
                Authentication userAuthentication = ((OAuth2Authentication) authentication).getUserAuthentication();
                LinkedHashMap<String, Object> details = (LinkedHashMap<String, Object>) userAuthentication.getDetails();
                ObjectMapper mapper = new ObjectMapper();
                mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
                try {
                    LinkedHashMap userAuthenticationIn = (LinkedHashMap) details.get(USER_AUTHENTICATION);
                    Object detailsIn = userAuthenticationIn.get(DETAILS);
                    authUser = new AuthUser(userAuthentication.getName(), userAuthentication.getCredentials().toString(), userAuthentication.getAuthorities());
                    String s = mapper.writeValueAsString(detailsIn);
                    MyMoreUserInfo myMoreUserInfo = mapper.readValue(s, MyMoreUserInfo.class);
                    Long storeId = myMoreUserInfo.getStoreId();
                    Long userId = myMoreUserInfo.getUserId();
                    authUser.setUserId(userId);
                    authUser.setStoreId(storeId);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return authUser;
            }
            if (authentication instanceof UsernamePasswordAuthenticationToken) {
                UsernamePasswordAuthenticationToken up = (UsernamePasswordAuthenticationToken) authentication;
                authUser = new AuthUser(up.getName(), AuthCommon.SSO_CREDENTIALS, up.getAuthorities());
                AuthWebAuthenticationDetails details = (AuthWebAuthenticationDetails) up.getDetails();
                Long storeId = details.getStoreId();
                Long userId = details.getUserId();
                authUser.setUserId(userId);
                authUser.setStoreId(storeId);
                return authUser;
            }
        }
        throw new UsernameNotFoundException("用户尚未登录");
    }

    public static Long loginUserId() {
        return getAuthUser().getUserId();
    }

    public static Long loginStoreId() {
        return getAuthUser().getStoreId();
    }

    public static String loginUsername() {
        return getAuthUser().getUsername();
    }

    public static class MyMoreUserInfo {
        private Long userId;
        private Long storeId;

        public Long getUserId() {
            return userId;
        }

        public void setUserId(Long userId) {
            this.userId = userId;
        }

        public Long getStoreId() {
            return storeId;
        }

        public void setStoreId(Long storeId) {
            this.storeId = storeId;
        }
    }
}